package item.pickable;

import item.*;
import attribute.*;
import be.kuleuven.cs.som.annotate.*;

/**
 *@invar A pickAble item can only be carried by a single robot at a time.
 *			|int i = 0
 *			|if(isOnARobot()) then
 *			|	 for each robot in this.getBoard().getListOfRobots())
 *			|		and for each pickableItem in robot.getListOfItemsHeld()){
 *			|			if(pickableItem == this)	i += 1
 * 			|	}
 *			|}
 *			|then i == 1
 *
 * @invar A pickAble item cannot both be owned by a robot and be located
 *				on a board at the same time.
 *			|!(this.isOnABoard && this.isOnARobot)
 *
 *@invar Each pickableItem must at all time have a valid weight.
 *			|isValidWeight(getWeight())
 *
 */
public abstract class PickableItem extends Item{
	private int weight;
	private final static int MIN_WEIGHT = 0;
	private final static int MAX_WEIGHT = Integer.MAX_VALUE;
	private boolean isOnARobot;

	/**
	 *	 Checks whether or not this pickAble item is being held by a robot.
	 *
	 * @return True if and only if isOnARobot is true
	 *			|result ==  this.isOnARobot;
	 */
	@Basic 
	public boolean isOnARobot(){
		return this.isOnARobot;
	}
	
	/**
	 * Set the boolean isOnARobot ascribed to this pick-up item to the given boolean value
	 * @param trueOrFalse
	 * 			The boolean value that has to be set as the value of isOnARobot
	 * 
	 * @post ...
	 * 			|this.new.isOnARobot() == trueOrFalse
	 */
	public void setIsOnARobot(boolean trueOrFalse){
		this.isOnARobot = trueOrFalse;
	}
	
	/**
	 * Return the weight of this pickAble item.
	 * 		The weight of a pickAble item expresses how much the pick-up item weighs in gram.
	 */
	@Basic
	public int getWeight() {
		return weight;
	}

	/**
	 * Set the weight of this pickAble item to the given weight after making it a valid weight.
	 * 
	 * @param weight
	 * 			The new weight for this pickAble item.
	 * 
	 * @post The new weight of this pickAble item is equal to the absolute value of this given amount of weight modulo the maximum amount of weight.
	 * 			|This.new.getWeight() == Math.abs(weight % MAX_WEIGHT)
	 */
	public void setWeight(int weight) {
		this.weight = Math.abs(weight % MAX_WEIGHT);
	}
	
	/**
	 * Check whether the given weight is a valid weight for any pickableItem.
	 * 
	 * @param weight
	 * 			The weight to check.
	 * @return ...
	 * 			|result == weight >= getMinWeight() && weight <= getMaxWeight()
	 */
	public static boolean isValidWeight(int weight){
		return weight >= getMinWeight() && weight <= getMaxWeight();
	}
	
	/**
	 * Returns the Max Weight.
	 */
	public static int getMaxWeight(){
		return MAX_WEIGHT;
	}
	
	/**
	 * Returns the Min Weight.
	 */
	public static int getMinWeight(){
		return MIN_WEIGHT;
	}
	

	/**
	 * Checks whether the given item can be put at the given position at the given board.
	 * 
	 * @param	p
	 * 			The position the item should be put at.
	 * 
	 * @param	board
	 * 			The board the position is on.
	 * 
	 * @return	...
	 * 			|if(p == null
	 * 			|	result == true
	 *			...
	 *			|result == p.hasItemOfClass(Wall.class) == false
	 */
	@Override
	public boolean canPutItemAt(Position p){
		if(p == null)
			return true;
		else
			return p.hasItemOfClass(Wall.class) == false;
	}

	
	@Override
	public abstract void hitByLaser();
}
